import { Ast, createRootAst } from "./ast";
import { BaseVisitor } from "./core";
import { getLiveRoomLink } from "./liveRoomLink";
import { getLiveRoomRedPackets } from "./red/LiveRoomRedPacketInfoVisitor";
import { createStorage, formatMinute, getDeviceUuid, httpPost, tryRun } from "./utils";

interface ScanFeed {
    username?: string,
    title?: string,
    count?: string,
    tip?: string,
    toUserInfo?: Function
}
export class ScanRoomInfoContext {
    is: boolean = false;
    toast: string = ``;
    living: boolean = false;

    closed: boolean = false;
    feeds: ScanFeed[] = [];

    isDialog: boolean = false;


    online: number = 0;
    name?: string;
    rank?: string;
    category?: string;
    redPacketCount?: number;
    status?: string;
    openTime?: string;


    reds: any[] = [];
    link: any;


    close?: () => void;
    follow?: () => void;
    more?: () => void;
    comment?: () => void;
    gift?: () => void;
    share?: () => void;
    open?: () => void;

    isEnd() {
        return this.toast === `已加载到底部`
    }
    isBusy() {
        return this.toast.includes(`过快`)
    }
    cancel: Function;
    back: Function;
}

class ScanRoomInfoVisitor extends BaseVisitor {
    visitViewPager(node: Ast, ctx: ScanRoomInfoContext) {
        /**
         * 检查是否在直播间
         */
        if (node.id.endsWith(`live_slide_view_pager`)) {
            ctx.is = true;
        }
        if (node.id.endsWith(`nasa_groot_view_pager`)) {
            ctx.is = false;
        }
        node.children.map(c => c.visit(this, ctx))
    }
    visitTextSwitcher(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.id.endsWith(`live_comment_text_view`) && node.clickable) {
            ctx.comment = () => node.click()
        }
        node.children.map(child => child.visit(this, ctx))
    }
    visitLinearLayout(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.id.endsWith(`live_right_pendant_container`) && node.clickable) {
            ctx.more = () => node.click()
        }
        node.children.map(child => child.visit(this, ctx))
    }
    private getLv(node: Ast) {
        return node.bounds.top / device.height;
    }
    lvMinNode: Ast;
    private getLvMin(node: Ast, min: number = 0.1) {
        if (this.getLv(node) > min) {
            this.lvMinNode = node;
            return;
        }
        node.children.find(c => this.getLvMin(c, min))
        return
    }
    private i: number = 0;
    visitFrameLayout(node: Ast, ctx: ScanRoomInfoContext) {
        if (!ctx.living) {
            // 顶级frame
            if (!node.parent) {
                const { left, right, top, bottom } = node.bounds;
                ctx.isDialog = top > 0;
                if (ctx.isDialog) {
                    this.getLvMin(node)
                    if (this.lvMinNode) {
                        const { left, right, top, bottom } = this.lvMinNode.bounds;
                        const x = (left + right) / 2;
                        const y = (top + 0) / 2;
                        const lv = this.getLv(this.lvMinNode)
                        this.i += 1;
                        ctx.cancel = () => click(x, y);
                    }
                }
            }
        }
        if (node.id.endsWith(`live_play_root_container`)) {
            ctx.living = true;
        }
        if (node.id.endsWith(`live_square_side_bar_layout_close_view`) && node.clickable) {
            ctx.close = () => node.click()
        }
        if (node.id.endsWith(`live_bottom_bar_gift_container`) && node.clickable) {
            ctx.gift = () => node.click()
        }
        node.children.map(c => c.visit(this, ctx))
    }
    visitTextView(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.text === `退出直播间`) {
            if (node.parent && node.parent.clickable) {
                node.parent?.click()
                return;
            }
        }
        if (node.text === `退出`) {
            if (node.parent && node.parent.clickable) {
                node.parent?.click()
                return;
            }
        }
        if (node.text === `立即关注`) {
            if (node.parent && node.parent.clickable) {
                back()
                return;
            }
        }
        if (node.id.endsWith('toast_text')) {
            ctx.toast = node.text;
        }
        if (node.id.endsWith(`live_play_closed_v3_title_text_view`) && node.text === `直播已结束`) {
            ctx.closed = true;
        }
        if (node.id.endsWith(`live_name_text`)) {
            ctx.name = node.text
        }
        if (node.id.endsWith(`live_follow_text`)) {
            ctx.follow = () => node.click()
        }
        if (node.id.endsWith(`live_audience_count_text`)) {
            ctx.online = parseInt(node.text)
        }
        if (node.id.endsWith(`live_hourly_rank_content_view`)) {
            ctx.rank = node.text
        }
        if (node.id.endsWith(`live_side_bar_pendant_text_view`)) {
            ctx.category = node.text
        }
        if (node.id && node.id.endsWith('live_red_packet_count')) {
            ctx.redPacketCount = parseInt(node.text)
        }
        if (node.id.endsWith(`live_red_packet_status_text`) && node.visibleToUser) {
            ctx.status = node.text;
            ctx.openTime = node.formatDate(node.second(node.toSecond()))
            const clickNode = node.findInParent(it=>it.clickable)
            if (clickNode) {
                ctx.open = () => {
                    clickNode.click()
                }
            }
        }
    }

    visitImageView(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.id.endsWith(`live_play_closed_v3_back_btn`)) {
            ctx.back = () => node.click()
        }
        if (node.id.endsWith(`live_red_packet_container_close_view`)) {
            ctx.cancel = () => node.click()
        }
        if (node.id.endsWith(`close_view`)) {
            ctx.cancel = () => node.click()
        }
    }



    visitRelativeLayout(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.id.endsWith(`live_bottom_bar_single_icon_container`) && node.clickable) {
            ctx.share = () => node.click()
        }
        node.children.map(child => child.visit(this, ctx))
    }

    visitRecyclerView(node: Ast, ctx: ScanRoomInfoContext) {
        if (node.id.endsWith(`live_play_closed_v2_feed_recycler_view`)) {
            // 其他直播间推荐
            ctx.feeds = node.children.map(child => {
                // 获取信息
                const feed: ScanFeed = {}
                child.children.map(c => {
                    if (c.id.endsWith(`live_square_side_bar_item_user_name_view`)) {
                        feed.username = c.text;
                    }
                    if (c.id.endsWith(`live_square_side_bar_item_title_text_view`)) {
                        feed.title = c.text;
                    }
                    if (c.id.endsWith(`live_square_side_bar_item_count_view`)) {
                        feed.count = c.text;
                    }
                    
                    if(c.id.endsWith('red_packet_cover_reward_usual_count')){
                        feed.count = c.text
                    }
                    if (c.id.endsWith(`live_cover_icon_text`)) {
                        feed.tip = c.text;
                    }
                    if (c.id.endsWith(`live_square_side_bar_item_cover_view`)) {
                        feed.toUserInfo = () => node.click()
                    }
                });
                if (Object.keys(feed).length > 0) return feed;
            }).filter(it => !!it)
        }
        node.children.map(c => c.visit(this, ctx))
    }
}

export function scanRoomInfo(that?: any) {
    const ctx = new ScanRoomInfoContext()
    const visitior = new ScanRoomInfoVisitor()
    const root = createRootAst()
    root.visit(visitior, ctx);
    let cancel = !!ctx.cancel;
    const isRuning = () => {
        if (that) return !!that.isRuning;
        return true;
    }
    while (cancel && isRuning()) {
        ctx.cancel()
        sleep(1000)
        const dtx = new ScanRoomInfoContext()
        const visitior = new ScanRoomInfoVisitor()
        const root = createRootAst()
        visitior.visitNode(root, dtx);
        cancel = !!dtx.cancel;
    }
    if (ctx.name && ctx.is) return ctx;
    return;
}

let preRoom: string;
let preCount: number = 0;
let max: number = 0;

function setTodayMax(max: number) {
    const storage = createStorage()
    const now = new Date();
    const str = `${now.getFullYear()}${now.getMonth() + 1}${now.getDate()}`
    storage.put(`TODAY_FOLLOW_${str}`, max)
}

function getTodayMax() {
    const storage = createStorage()
    const now = new Date();
    const str = `${now.getFullYear()}${now.getMonth() + 1}${now.getDate()}`
    return storage.get(`TODAY_FOLLOW_${str}`, 0)
}

export function scanRoomRedInfo(ctx: any = {}) {
    let status: string = `0`;
    const start_time = new Date().getTime() / 1000;
    let roomInfo: ScanRoomInfoContext;
    roomInfo = scanRoomInfo(ctx);
    const logger = (msg: string) => ctx.log ? ctx.log.bind(ctx)(msg) : log(msg);
    const isTimeout = (timeout: number = 15) => (new Date().getTime() / 1000 - start_time) < timeout
    const isStop = () => {
        if (ctx) return !!ctx.isRuning;
        return false;
    }
    while (!(roomInfo && roomInfo.open) && isTimeout() && isStop()) {
        sleep(1000)
        roomInfo = scanRoomInfo(ctx);
    }
    // 等待加载红包 
    if (!roomInfo) {
        return status;
    }
    if (preRoom === roomInfo.name) {
        preCount += 1;
    } else {
        preCount = 0;
    }
    if (preCount > 3) {
        preCount = 0;
        return `3`
    }
    preRoom = roomInfo.name;
    ctx?.setRoomName(preRoom)
    if (roomInfo.closed) {
        return status;
    }
    status = `2`
    if (roomInfo.isBusy()) {
        logger(`操作太快了`)
        sleep(1000 * 10)
    }
    if (roomInfo && roomInfo.open) {
        roomInfo.open()
        sleep(1000 * 3)
        const root = createRootAst()
        const redsCtx = getLiveRoomRedPackets(root);
        if (redsCtx) {
            const reds = redsCtx.list;
            if (reds && reds.length > 0) {
                // 检查红包类型
                const filterReds = reds.filter(red => {
                    if (red.type === `快币`) {
                        return true;
                    }
                    if (red.type === '口令') {
                        return true;
                    }
                    if (red.type === `穿云箭`) {
                        return true;
                    }
                    if (red.type === '粉丝团') {
                        return false;
                    }
                    if (red.type === '分享') {
                        return false;
                    }
                    return false;
                }).sort((a, b) => a.count - b.count)
                roomInfo.reds = filterReds;
                tryRun(() => redsCtx.close && redsCtx.close())
                sleep(2000)
                if (filterReds && filterReds.length > 0) {
                    const roomLink = getLiveRoomLink(10)
                    roomInfo.link = roomLink;
                    if (roomLink) {
                        const { link, name, obj } = roomLink;
                        if (!obj) return status;
                        ctx?.setRoomName && ctx?.setRoomName(name)
                        ctx?.setRoomUserId && ctx?.setRoomUserId(obj['userId'])
                        status = `1`
                        tryRun(() => {
                            httpPost('addRedPkg', {
                                link,
                                name,
                                online: roomInfo.online,
                                openTime: roomInfo.openTime,
                                readPacketCount: roomInfo.redPacketCount,
                                category: roomInfo.category,
                                rank: roomInfo.rank,
                                uuid: getDeviceUuid(),
                                ...(obj || {}),
                                redPackets: filterReds.map(red => ({
                                    type: red.type,
                                    count: red.count,
                                    total: red.total,
                                    text: red.desc,
                                    password: red.password,
                                    unit: red.unit,
                                    sub_title: red.sub_title,
                                    title: red.title,
                                    desc: red.desc,
                                }))
                            });
                        })
                        return status;
                    }
                }
            }
        }
    }
    logger(`扫描房间及红包信息 ${formatMinute(new Date().getTime() / 1000 - start_time)}`)
    if (roomInfo.isEnd()) {
        logger(`最后一个了`)
        status = `3`;
    }
    return status;
}
